<template>
  <div class="image-cropper">
    <a-modal
      v-model:open="open"
      title="图片编辑"
      @ok="handleCrop"
      @cancel="closeModal"
      style="text-align: center"
    >
      <vue-cropper
        ref="cropperRef"
        class="vue-cropper"
        :img="picture.url"
        :autoCrop="true"
        :fixedBox="false"
        :centerBox="true"
        :canMove="false"
        :info="true"
        outputType="png"
        style="width: 400px; height: 400px"
      />
      <div style="margin-bottom: 16px" />
      <div class="image-enter-actions" v-if="isTeamSpace">
        <a-space>
          <a-button v-if="editUser" :disabled="editUser.id"
            >{{ editUser.userName }} 正在编辑
          </a-button>
          <a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
          <a-button v-if="canExitEdit" danger ghost @click="exitEdit">退出编辑</a-button>
        </a-space>
      </div>
      <!-- 图片操作 -->
      <div class="image-cropper-actions">
        <a-space>
          <a-button :disabled="!canEdit" @click="rotateLeft">向左旋转</a-button>
          <a-button :disabled="!canEdit" @click="rotateRight">向右旋转</a-button>
          <a-button :disabled="!canEdit" @click="changeScale(1)">放大</a-button>
          <a-button :disabled="!canEdit" @click="changeScale(-1)">缩小</a-button>
        </a-space>
      </div>
    </a-modal>
  </div>
</template>
<script lang="ts" setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import { computed, onUnmounted, ref, watch } from 'vue'
import { savePictureUsingPost } from '@/api/pictureController.ts'
import { useUserStore } from '@/stores/user.ts'
import PictureEditWebSocket from '@/utils/websocket.ts'
import { PICTURE_EDIT_ACTION_ENUM, PICTURE_EDIT_MESSAGE_TYPE_ENUM } from '@/constants/picture.ts'
import { message } from 'ant-design-vue'
import { SPACE_TYPE_ENUM } from '@/constants/space.ts'

const open = defineModel()

interface Props {
  picture: API.PictureVO
  spaceId: number
  onSuccess: (newPicture: API.PictureVO) => void
  space: API.SpaceVO
}

const props = withDefaults(defineProps<Props>(), {})

// 判断是不是团队空间
const isTeamSpace = computed(() => {
  return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM
})
// 打开modal
const openModal = () => {
  open.value = true
}

defineExpose({
  openModal,
})
const editUser = ref<API.UserVO>()

// 编辑器组件的引用
const cropperRef = ref()

// 处理截图
const handleCrop = () => {
  cropperRef.value.getCropBlob((blob) => {
    const fileName = `${props.picture.name ?? 'image'}.png`
    const file = new File([blob], fileName, { type: blob.type })
    handleUpload({ file })
  })
  //   关闭websocket
  if (webSocket) {
    webSocket.disconnect()
  }
  editUser.value = undefined
}

// 图片编辑
const userStore = useUserStore()
const loginUser = userStore.userInfo

// 权限
const canEnterEdit = computed(() => {
  return !editUser.value
})
const canExitEdit = computed(() => {
  return editUser.value?.id === loginUser?.id
})
const canEdit = computed(() => {
  if (!isTeamSpace.value) {
    return true
  }
  return editUser.value?.id === loginUser?.id
})

// websocket
let webSocket: PictureEditWebSocket | null

// 初始化连接
const initWebsocket = () => {
  // 没有图片或弹框未打开
  const pictureId = props.picture?.id
  if (!pictureId || !open.value) {
    return
  }

  // 清理未关闭的
  if (webSocket) {
    webSocket.disconnect()
  }

  //   建立连接
  webSocket = new PictureEditWebSocket(pictureId)
  webSocket.connect()

  // 监听通知消息
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (info) => {
    message.info(info.message)
  })

  //   监听错误消息
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (info) => {
    message.error(info.message)
  })

  // 监听编辑状态
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (info) => {
    editUser.value = info.userVO
    switch (info.editAction) {
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
        cropperRef.value.rotateLeft()
        break
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
        cropperRef.value.rotateRight()
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
        cropperRef.value.changeScale(-1)
        break
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
        cropperRef.value.changeScale(1)
        break
    }
  })

  //   监听进入编辑消息
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (info) => {
    message.info(info.message)
    editUser.value = info.userVO
  })

  //   监听退出编辑消息
  webSocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (info) => {
    message.info(info.message)
    editUser.value = undefined
  })
}

watch(
  () => open.value,
  () => {
    if (isTeamSpace.value) {
      initWebsocket()
    }
  },
)
// 组件销毁
onUnmounted(() => {
  if (webSocket) {
    webSocket.disconnect()
  }
  editUser.value = undefined
})

// 进入编辑
const enterEdit = () => {
  if (webSocket) {
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
    })
  }
}
// 退出编辑
const exitEdit = () => {
  if (webSocket) {
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
    })
  }
}
// 进行编辑
const editAction = (action: string) => {
  if (webSocket) {
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction: action,
    })
  }
}

// 向左旋转
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}

// 向右旋转
const rotateRight = () => {
  cropperRef.value.rotateRight()
  editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}

// 缩放
const changeScale = (num: number) => {
  cropperRef.value.changeScale(num)
  editAction(num > 0 ? PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT : PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
}

// 关闭modal
const closeModal = () => {
  //   清理websocket
  if (webSocket) {
    webSocket.disconnect()
  }
  editUser.value = undefined
}

// 上传文件
const loading = ref(false)
const handleUpload = async ({ file }: any) => {
  loading.value = true
  try {
    const params = props.picture ? { id: props.picture.id } : {}
    const res = await savePictureUsingPost(
      {
        ...params,
        spaceId: props.spaceId,
      },
      {},
      file,
    )
    if (res.data?.code != 0) {
      return
    }
    props.onSuccess?.(res.data?.data)
    open.value = false
  } catch (error) {
    console.log(error.message)
  }
  loading.value = false
}
</script>

<style lang="scss"></style>
